<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Drag and Drop in PySide</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="PySide, tutorial, Python, drag and drop, Linux, GUI, learn PySide">
<meta name="description" content="This part of the PySide tutorial covers drag and drop operations">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container2">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content2">


<a href="/" title="Home">Home</a>&nbsp;
<a href=".." title="Home">Contents</a>


<h1>Drag and Drop in PySide</h1>


<p>
In this part of the PySide tutorial, we will talk about drag &amp; 
drop operations.
</p>

<div class="big_hor">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* big_horizontal */
google_ad_slot = "2904953388";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
In computer graphical user interfaces, drag-and-drop is the action of 
(or support for the action of) clicking on a virtual object and dragging 
it to a different location or onto another virtual object. In general, 
it can be used to invoke many kinds of actions, or create various types 
of associations between two abstract objects. (Wikipedia)
</p>

<p>
Drag and drop functionality is one of the most visible aspects of the 
graphical user interface. Drag and drop operation enables users to do 
complex things intuitively. 
</p>

<p>
Usually, we can drag and drop two things. Data or some graphical objects. 
If we drag an image from one application to another, we drag and drop binary 
data. If we drag a tab in Firefox and move it to another place, we drag and drop a 
graphical component. 
</p>


<h2>Simple Drag and Drop</h2>

<p>
In the first example, we will have a <code>QtGui.QLineEdit</code> and a 
<code>QtGui.QPushButton</code>. We will drag plain text from 
the line edit widget and drop it onto the button widget. 
</p>

<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PySide tutorial 

This is a simple drag and
drop example.  

author: Jan Bodnar
website: zetcode.com 
last edited: August 2011
"""

import sys
from PySide import QtGui, QtCore

class Button(QtGui.QPushButton):
  
    def __init__(self, title, parent):
        super(Button, self).__init__(title, parent)
        
        self.setAcceptDrops(True)

    def dragEnterEvent(self, e):
      
        if e.mimeData().hasFormat('text/plain'):
            e.accept()
        else:
            e.ignore() 

    def dropEvent(self, e):
        self.setText(e.mimeData().text())
        

class Example(QtGui.QWidget):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):      
    
        qe = QtGui.QLineEdit('', self)
        qe.setDragEnabled(True)
        qe.move(30, 65)

        button = Button("Button", self)
        button.move(190, 65) 

        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Simple Drag &amp; Drop')
        self.show()              
        
def main():
    
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
</pre>

<p>
Simple drag &amp; drop operation.
</p>

<pre class="explanation">
class Button(QtGui.QPushButton):
  
    def __init__(self, title, parent):
        super(Button, self).__init__(title, parent)
</pre>

<p>
In order to drop text on the <code>QtGui.QPushButton</code> widget, we 
must reimplement some methods. So we create 
our own Button class, which will inherit from the <code>QtGui.QPushButton</code> class. 
</p>

<pre class="explanation">
self.setAcceptDrops(True)
</pre>

<p>
We enable drop events for the widget.
</p>

<pre class="explanation">
def dragEnterEvent(self, e):
  
    if e.mimeData().hasFormat('text/plain'):
        e.accept()
    else:
        e.ignore() 
</pre>

<p>
First we reimplement the <code>dragEnterEvent()</code> method. We inform 
about the data type, we will accept. In our case it is 
plain text. 
</p>

<pre class="explanation">
def dropEvent(self, e):
    self.setText(e.mimeData().text()) 
</pre>

<p>
By reimplementing the <code>dropEvent()</code> method, we will define, what 
we will do upon the drop event. Here we change the
text of the button widget. 
</p>

<pre class="explanation">
qe = QtGui.QLineEdit('', self)
qe.setDragEnabled(True)
</pre>

<p>
The <code>QtGui.QLineEdit</code> widget has a built-in support for drag operations. 
All we need to do is to call <code>setDragEnabled()</code> method
to activate it.
</p>


<img src="/img/gui/pyside/simpledd.png" alt="Simple Drag &amp; Drop">
<div class="figure">Figure: Simple Drag &amp; Drop</div>



<h2>Drag &amp; drop a button widget</h2>

<p>
In the following example, we will demonstrate, how to drag &amp; 
drop a button widget. 
</p>

<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
ZetCode PySide tutorial 

In this example, we drag and drop a
button.

author: Jan Bodnar
website: zetcode.com 
last edited: August 2011
"""

import sys
from PySide import QtGui, QtCore

class Button(QtGui.QPushButton):
  
    def __init__(self, title, parent):
        super(Button, self).__init__(title, parent)

    def mouseMoveEvent(self, e):

        if e.buttons() != QtCore.Qt.RightButton:
            return

        mimeData = QtCore.QMimeData()

        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(e.pos() - self.rect().topLeft())

        dropAction = drag.start(QtCore.Qt.MoveAction)


    def mousePressEvent(self, e):
      
        QtGui.QPushButton.mousePressEvent(self, e)
        if e.button() == QtCore.Qt.LeftButton:
            print 'press'
        

class Example(QtGui.QWidget):
    
    def __init__(self):
        super(Example, self).__init__()
        
        self.initUI()
        
    def initUI(self):      
    
        self.setAcceptDrops(True)

        self.btn = Button('Button', self)
        self.btn.move(100, 65)

        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Click or move')
        self.show()

    def dragEnterEvent(self, e):
      
        e.accept()

    def dropEvent(self, e):

        position = e.pos()
        self.btn.move(position)

        e.setDropAction(QtCore.Qt.MoveAction)
        e.accept()
        
def main():
    
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
</pre>

<p>
In our code example, we have a <code>QtGui.QPushButton</code> on the window. 
If we click on the button with a left mouse button, 
we print 'press' to the console. By right clicking and moving 
the button, we perform a drag &amp; drop operation 
on the button widget. 
</p>

<pre class="explanation">
class Button(QtGui.QPushButton):
  
    def __init__(self, title, parent):
        super(Button, self).__init__(title, parent)
</pre>

<p>
We create a Button class, which will derive from the <code>QtGui.QPushButton</code>. 
We also reimplement two methods of the <code>QtGui.QPushButton</code>, the
<code>mouseMoveEvent()</code> and <code>mousePressEvent()</code>. 
The mouseMoveEvent() method is the place, where the drag &amp;
drop operation begins.
</p>

<pre class="explanation">
if event.buttons() != QtCore.Qt.RightButton:
    return
</pre>

<p>
Here we decide, that we can perform drag &amp; drop only with a 
right mouse button. The left mouse button is reserved
for clicking on the button.
</p>

<pre class="explanation">
mimeData = QtCore.QMimeData()

drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(event.pos() - self.rect().topLeft())
</pre>

<p>
Here we create a <code>QtGui.QDrag</code> object.  
</p>

<pre class="explanation">
dropAction = drag.start(QtCore.Qt.MoveAction)
</pre>

<p>
The <code>start()</code> method of the drag object starts the 
drag &amp; drop operation. 
</p>

<pre class="explanation">
def mousePressEvent(self, e):
  
    QtGui.QPushButton.mousePressEvent(self, e)
    if e.button() == QtCore.Qt.LeftButton:
        print 'press'
</pre>

<p>
We print 'press' to the console, if we left click on the button 
with the mouse. Notice that we call <code>mousePressEvent()</code> method
on the parent as well. Otherwise we would not see the button being pushed. 
</p>

<pre class="explanation">
position = e.pos()

self.btn.move(position)
</pre>

<p>
In the <code>dropEvent()</code> method we code, what happens after we release 
the mouse button and finish the drop operation. We find out the current
mouse pointer position and move a button accordingly.
</p>

<pre class="explanation">
e.setDropAction(QtCore.Qt.MoveAction)
e.accept()
</pre>

<p>
We specify the type of the drop action. In our case it is a move action.
</p>

<p>
This part of the PySide tutorial was dedicated to drag and drop.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br> 

<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified August 28, 2011  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

